package com.icekrvams.air.versionchecker

import android.content.Context
import android.content.pm.PackageInfo
import android.content.pm.PackageManager
import com.icekrvams.air.mmkv

/**
 * 本地版本检查、记录。
 */
object LocalVersionChecker {

    /**
     * 当前安装的版本号。
     */
    fun getCurrentVersionCode(context: Context): Int {
        try {
            val packageManager: PackageManager = context.packageManager
            val packageInfo: PackageInfo = packageManager.getPackageInfo(
                context.packageName, 0
            )
            return packageInfo.versionCode
        } catch (ignored: PackageManager.NameNotFoundException) {
        }
        return -1
    }

    /**
     * 当前安装的版本名称。
     */
    fun getCurrentVersionName(context: Context): String? {
        try {
            val packageManager = context.packageManager
            val packageInfo: PackageInfo = packageManager.getPackageInfo(context.packageName, 0)
            return packageInfo.versionName
        } catch (ignored: PackageManager.NameNotFoundException) {
        }
        return null
    }

    const val INVALID_CODE = -9527

    const val INVALID_TIME = -9527L

    // 应用首次安装时的版本号。
    private const val PREF_FIRST_INSTALL_VERSION_CODE = "first_install_version_code"

    // 上次安装的版本号。
    private const val PREF_PREV_VERSION_CODE = "prev_version_code"

    // 当前版本号。
    private const val PREF_CURR_VERSION_CODE = "curr_version_code"

    // 首次安装时间。
    private const val PREF_FIRST_INSTALL_TIME = "first_install_time"

    // 是否为更新的首次启动。
    private const val PREF_IS_FIRST_StART_AFTER_UPGRADE = "is_first_start_after_upgrade"

    // 是否应该弹升级弹窗
    const val PREF_SHOULD_SHOW_UPDATE_DIALOG = "pref_should_show_update_dialog"

    // 是否应该弹升级提醒
    const val PREF_SHOULD_SHOW_WHATS_NEW_DIALOG = "pref_should_show_whats_new_dialog"

    // 默认版本号。
    private const val UNINITIALIZED_VERSION_CODE = -1

    internal fun initialize(context: Context) {
        // 记录的本号。
        val recordedVersionCode =
            mmkv.decodeInt(PREF_CURR_VERSION_CODE, UNINITIALIZED_VERSION_CODE)
        // 当前版本号。
        val currentVersionCode = getCurrentVersionCode(context)
        // 未记录版本号，判定为首次安装。
        if (recordedVersionCode == UNINITIALIZED_VERSION_CODE) {
            // 记录当前版本号。
            mmkv.encode(PREF_CURR_VERSION_CODE, currentVersionCode)
            // 记录首次安装版本号。
            mmkv.encode(PREF_FIRST_INSTALL_VERSION_CODE, currentVersionCode)
            // 记录之前版本号。
            mmkv.encode(PREF_PREV_VERSION_CODE, recordedVersionCode)
            // 记录首次安装时间。
            val currentTimeStamp = System.currentTimeMillis()
            mmkv.encode(PREF_FIRST_INSTALL_TIME, currentTimeStamp)
            return
        }
        // 记录的版本号与当前版本号不同，判定为更新。
        if (recordedVersionCode != currentVersionCode) {
            // 记录当前版本号。
            mmkv.encode(PREF_CURR_VERSION_CODE, currentVersionCode)
            // 记录之前版本号。
            mmkv.encode(PREF_PREV_VERSION_CODE, recordedVersionCode)
            // 记录当前状态为更新。
            mmkv.encode(PREF_IS_FIRST_StART_AFTER_UPGRADE, true)

            mmkv.encode(PREF_SHOULD_SHOW_UPDATE_DIALOG, true)
            mmkv.encode(PREF_SHOULD_SHOW_WHATS_NEW_DIALOG, true)
        } else {
            // 移除更新状态，如果没有自动移除该状态，且开发者没有手动移除，则会在下次冷启动时移除。
            mmkv.encode(PREF_IS_FIRST_StART_AFTER_UPGRADE, false)
        }
    }

    /**
     * 获取首次安装版本号。
     * 如未获取到，返回 [INVALID_CODE]。
     */
    fun getFirstInstallVersionCode() =
        mmkv.getInt(PREF_FIRST_INSTALL_VERSION_CODE, INVALID_CODE)

    /**
     * 获取上次安装版本号。
     * 如未获取到，返回[INVALID_CODE]。
     */
    fun getPrevVersionCode() =
        mmkv.getInt(PREF_PREV_VERSION_CODE, INVALID_CODE)

    /**
     * 获取首次安装时间。
     * 如未获取到，返回[INVALID_TIME]。
     */
    fun getFirstInstallTime() =
        mmkv.getLong(PREF_FIRST_INSTALL_TIME, INVALID_TIME)

    /**
     * 判断是否为更新后首次启动。
     * @param onceCheck 设置为 true，则结果的 true 状态仅可以访问一次，访问后被置为 false。
     * 否则其会在以下两种情况下才会被置为 false：
     * 1.开发者手动调用 [removeFirstStartAfterUpgradeStatus]。
     * 2.下次冷启动时，SDK 自动调用 [initialize]。
     */
    @JvmOverloads
    fun isFirstStartAfterUpgrade(onceCheck: Boolean = true): Boolean {
        val isFirstStartAfterUpgrade = mmkv.decodeBool(
            PREF_IS_FIRST_StART_AFTER_UPGRADE, false
        )
        if (onceCheck && isFirstStartAfterUpgrade) {
            removeFirstStartAfterUpgradeStatus()
        }
        return isFirstStartAfterUpgrade
    }

    /**
     * 手动移除"这是更新后首次启动"的状态。
     */
    fun removeFirstStartAfterUpgradeStatus() {
        mmkv.encode(PREF_IS_FIRST_StART_AFTER_UPGRADE, false)
    }
}


